home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / ULARN.ARJ / ULARN.TAR / ularn / movem.c < prev    next >
C/C++ Source or Header  |  1989-10-25  |  11KB  |  470 lines

  1. /*
  2.  *    movem.c (move monster)        Larn is copyrighted 1986 by Noah Morgan.
  3.  *
  4.  *    Here are the functions in this file:
  5.  *
  6.  *    movemonst()        Routine to move the monsters toward the player
  7.  *        Function to move a monster at (x,y) -- must determine where
  8.  *    movemt(x,y)        
  9.  *        Function to actually perform the monster movement
  10.  *    mmove(x,y,xd,yd)    
  11.  *        Function to look for and move spheres of annihilation
  12.  *    movsphere()         
  13.  */
  14. #include "header.h"
  15.  
  16. /*
  17.  *    movemonst()        Routine to move the monsters toward the player
  18.  *
  19.  *    This routine has the responsibility to determine which monsters are to
  20.  *    move, and call movemt() to do the move.
  21.  *    Returns no value.
  22.  */
  23. static short w1[9],w1x[9],w1y[9];
  24. static int tmp1,tmp2,tmp3,tmp4,distance;
  25. movemonst()
  26. {
  27.     register int i,j;
  28.     if (c[TIMESTOP]) return;    /* no action if time is stopped */
  29.     if (c[HASTESELF])  if ((c[HASTESELF]&1)==0)  return;
  30.     if (spheres) movsphere();    /* move the spheres of annihilation if any */
  31.     if (c[HOLDMONST])  return;    /* no action if monsters are held */
  32.  
  33.     if (c[AGGRAVATE])    /* determine window of monsters to move */
  34.     {
  35.         tmp1=playery-5; 
  36.         tmp2=playery+6; 
  37.         tmp3=playerx-10; 
  38.         tmp4=playerx+11;
  39.         distance=40; /* depth of intelligent monster movement */
  40.     }
  41.     else
  42.     {
  43.         tmp1=playery-3; 
  44.         tmp2=playery+4; 
  45.         tmp3=playerx-5; 
  46.         tmp4=playerx+6;
  47.         distance=17; /* depth of intelligent monster movement */
  48.     }
  49.  
  50.     if (level == 0) /* if on outside level monsters can move in perimeter */
  51.     {
  52.         if (tmp1 < 0) tmp1=0;         
  53.         if (tmp2 > MAXY) tmp2=MAXY;
  54.         if (tmp3 < 0) tmp3=0;         
  55.         if (tmp4 > MAXX) tmp4=MAXX;
  56.     }
  57.     else /* if in a dungeon monsters can't be on the perimeter (wall there) */
  58.     {
  59.         if (tmp1 < 1) tmp1=1;         
  60.         if (tmp2 > MAXY-1) tmp2=MAXY-1;
  61.         if (tmp3 < 1) tmp3=1;         
  62.         if (tmp4 > MAXX-1) tmp4=MAXX-1;
  63.     }
  64.  
  65.     for (j=tmp1; j<tmp2; j++) /* now reset monster moved flags */
  66.         for (i=tmp3; i<tmp4; i++)
  67.             moved[i][j] = 0;
  68.     moved[lasthx][lasthy]=0;
  69.  
  70.     if (c[AGGRAVATE] || !c[STEALTH]) /* who gets moved? split for efficiency */
  71.     {
  72.         for (j=tmp1; j<tmp2; j++) /* look thru all locations in window */
  73.             for (i=tmp3; i<tmp4; i++)
  74.                 if (mitem[i][j])    /* if there is a monster to move */
  75.                     if (moved[i][j]==0)    /* if it has not already been moved */
  76.                         movemt(i,j);    /* go and move the monster */
  77.     }
  78.     else /* not aggravated and not stealth */
  79.     {
  80.         for (j=tmp1; j<tmp2; j++) /* look thru all locations in window */
  81.             for (i=tmp3; i<tmp4; i++)
  82.                 if (mitem[i][j])    /* if there is a monster to move */
  83.                     if (moved[i][j]==0)    /* if it has not already been moved */
  84.                         if (stealth[i][j])    /* if it is asleep due to stealth */
  85.                             movemt(i,j);    /* go and move the monster */
  86.     }
  87.  
  88.     if (mitem[lasthx][lasthy]) /* now move monster last hit by player if not already moved */
  89.     {
  90.         if (moved[lasthx][lasthy]==0)    /* if it has not already been moved */
  91.         {
  92.             movemt(lasthx,lasthy);
  93.             lasthx = w1x[0];   
  94.             lasthy = w1y[0];
  95.         }
  96.     }
  97. }
  98.  
  99. /*
  100.  *        Function to move a monster at (x,y) -- must determine where
  101.  *    movemt(x,y)        
  102.  *    int x,y;
  103.  *
  104.  *    This routine is responsible for determining where one monster at (x,y) 
  105.  *    will move to.  Enter with the monsters coordinates in (x,y).
  106.  *    Returns no value.
  107.  */
  108. static int tmpitem,xl,xh,yl,yh;
  109.  
  110. movemt(i,j)
  111. int i,j;
  112. {
  113.     register int k,m,z,tmp,xtmp,ytmp,monst;
  114.     switch(monst=mitem[i][j])  /* for half speed monsters */
  115.     {
  116.     case TROGLODYTE:  
  117.     case HOBGOBLIN:  
  118.     case METAMORPH:  
  119.     case XVART:
  120.     case INVISIBLESTALKER:  
  121.     case ICELIZARD: 
  122.         if ((gtime & 1) == 1) return;
  123.     };
  124.     /* choose destination randomly if scared */
  125.     tmp=0;
  126.     {
  127.         register int i, j;
  128.         for (i=0; i<26; i++)
  129.             if (iven[i]==OHANDofFEAR){
  130.                 tmp=1;
  131.                 break;
  132.             }
  133.     }
  134.     if (c[SCAREMONST]){
  135.         if (tmp==1) tmp=2;
  136.     }
  137.     else if ((tmp==1) && (rnd(10) > 4)) tmp=0;
  138.  
  139.     if ((monst > DEMONLORD)||(monst == PLATINUMDRAGON)) {
  140.         tmp = (tmp==1) ? 0 : (rnd(10) > 5);
  141.     }
  142.     if (tmp) {
  143.         if ((xl = i+rnd(3)-2) < 0) xl=0;  
  144.         if (xl >= MAXX) xl=MAXX-1;
  145.         if ((yl = j+rnd(3)-2) < 0) yl=0;  
  146.         if (yl >= MAXY) yl=MAXY-1;
  147.         if ((tmp=item[xl][yl]) != OWALL)
  148.             if (mitem[xl][yl] == 0)
  149.                 if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
  150.                     if (tmp != OCLOSEDDOOR)        
  151.                         mmove(i,j,xl,yl);
  152.         return;
  153.     }
  154.  
  155.     if (monster[monst].intelligence > 10-c[HARDGAME]) /* if smart monster */
  156.         /* intelligent movement here -- first setup screen array */
  157.     {
  158.         xl=tmp3-2; 
  159.         yl=tmp1-2; 
  160.         xh=tmp4+2;  
  161.         yh=tmp2+2;
  162.         vxy(&xl,&yl);  
  163.         vxy(&xh,&yh);
  164.         for (k=yl; k<yh; k++)
  165.             for (m=xl; m<xh; m++)
  166.             {
  167.                 if (monst>=DEMONPRINCE) 
  168.                     screen[m][k]=0;
  169.                 else
  170.                     switch(item[m][k])
  171.                     {
  172.                     case OWALL: 
  173.                     case OELEVATORUP:
  174.                     case OELEVATORDOWN:
  175.                     case OPIT: 
  176.                     case OTRAPARROW: 
  177.                     case ODARTRAP:
  178.                     case OCLOSEDDOOR: 
  179.                     case OTRAPDOOR: 
  180.                     case OTELEPORTER:
  181. smm:                  
  182.                         screen[m][k]=127;  
  183.                         break;
  184.                     case OMIRROR: 
  185.                         if (mitem[m][k]==VAMPIRE) goto smm;
  186.                     default:  
  187.                         screen[m][k]=0;  
  188.                         break;
  189.                     };
  190.             }
  191.         screen[playerx][playery]=1;
  192.  
  193.         /* now perform proximity ripple from playerx,playery to monster */
  194.         xl=tmp3-1; 
  195.         yl=tmp1-1; 
  196.         xh=tmp4+1;  
  197.         yh=tmp2+1;
  198.         vxy(&xl,&yl);  
  199.         vxy(&xh,&yh);
  200.         for (tmp=1; tmp<distance; tmp++)    /* only up to 20 squares away */
  201.             for (k=yl; k<yh; k++)
  202.                 for (m=xl; m<xh; m++)
  203.                     if (screen[m][k]==tmp) /* if find proximity n advance it */
  204.                         for (z=1; z<9; z++) /* go around in a circle */
  205.                         {
  206.                             if (screen[xtmp=m+diroffx[z]][ytmp=k+diroffy[z]]==0)
  207.                                 screen[xtmp][ytmp]=tmp+1;
  208.                             if (xtmp==i && ytmp==j) goto out;
  209.                         }
  210.  
  211. out:  
  212.         if (tmp<distance) /* did find connectivity */
  213.             /* now select lowest value around playerx,playery */
  214.             for (z=1; z<9; z++) /* go around in a circle */
  215.                 if (screen[xl=i+diroffx[z]][yl=j+diroffy[z]]==tmp)
  216.                     if (!mitem[xl][yl]) { 
  217.                         mmove(i,j,w1x[0]=xl,w1y[0]=yl); 
  218.                         return; 
  219.                     }
  220.     }
  221.  
  222.     /* dumb monsters move here */
  223.     xl=i-1;  
  224.     yl=j-1;  
  225.     xh=i+2;  
  226.     yh=j+2;
  227.     if (i<playerx) xl++; 
  228.     else if (i>playerx) --xh;
  229.     if (j<playery) yl++; 
  230.     else if (j>playery) --yh;
  231.     for (k=0; k<9; k++) w1[k] = 10000;
  232.  
  233.     for (k=xl; k<xh; k++)
  234.         for (m=yl; m<yh; m++) /* for each square compute distance to player */
  235.         {
  236.             tmp = k-i+4+3*(m-j);
  237.             tmpitem = item[k][m];
  238.             if (tmpitem!=OWALL || (k==playerx && m==playery))
  239.                 if (mitem[k][m]==0)
  240.                     if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
  241.                         if (tmpitem!=OCLOSEDDOOR)
  242.                         {
  243.                             w1[tmp] = (playerx-k)*(playerx-k)+(playery-m)*(playery-m);
  244.                             w1x[tmp] = k;  
  245.                             w1y[tmp] = m;
  246.                         }
  247.         }
  248.  
  249.     tmp = 0;
  250.     for (k=1; k<9; k++)  if (w1[tmp] > w1[k])  tmp=k;
  251.  
  252.     if (w1[tmp] < 10000)
  253.         if ((i!=w1x[tmp]) || (j!=w1y[tmp]))
  254.             mmove(i,j,w1x[tmp],w1y[tmp]);
  255. }
  256.  
  257. /*
  258.  *        Function to actually perform the monster movement
  259.  *    mmove(x,y,xd,yd)    
  260.  *        int x,y,xd,yd;
  261.  *
  262.  *    Enter with the from coordinates in (x,y) and the destination coordinates
  263.  *    in (xd,yd).
  264.  */
  265. mmove(aa,bb,cc,dd)
  266. int aa,bb,cc,dd;
  267. {
  268.     register int tmp,i,x,flag;
  269.     char *who,*p;
  270.  
  271.     flag=0;    /* set to 1 if monster hit by arrow trap */
  272.     if ((cc==playerx) && (dd==playery)) {
  273.         hitplayer(aa,bb);  
  274.         moved[aa][bb] = 1;  
  275.         return;
  276.     }
  277.     i=item[cc][dd];
  278.     if ((i==OPIT) || (i==OTRAPDOOR))
  279.         switch(mitem[aa][bb]) {
  280.         case SPIRITNAGA:
  281.         case PLATINUMDRAGON:
  282.         case WRAITH:
  283.         case VAMPIRE:
  284.         case SILVERDRAGON:
  285.         case POLTERGEIST:
  286.         case DEMONLORD:    
  287.         case DEMONLORD+1:
  288.         case DEMONLORD+2:
  289.         case DEMONLORD+3:
  290.         case DEMONLORD+4:
  291.         case DEMONLORD+5:
  292.         case DEMONLORD+6:
  293.         case DEMONPRINCE:
  294.         case LUCIFER:
  295.             break;
  296.  
  297.         default:
  298.             mitem[aa][bb]=0; /* fell in a pit or trapdoor */
  299.         };
  300.     tmp = mitem[cc][dd] = mitem[aa][bb];
  301.     if (i==OANNIHILATION)
  302.         if (tmp>=DEMONLORD) /* demons dispel spheres */
  303.         {
  304.             flag=0;
  305.             for (x=0;x<26;x++)
  306.                 if(iven[x]==OSPHTALISMAN) flag++;
  307.             if (flag==0 
  308.                 || (flag && tmp == LUCIFER && (rnd(10) > 7))) {
  309.                 cursors();
  310.             lprintf("\nThe %s dispels the sphere!",
  311.                 monster[tmp].name);
  312.                 rmsphere(cc,dd);    /* delete the sphere */
  313.             }
  314.             else i=tmp=mitem[cc][dd]=0;
  315.         }
  316.         else i=tmp=mitem[cc][dd]=0;
  317.  
  318.     stealth[cc][dd]=1;
  319.     flag=0;
  320.  
  321.     if ((hitp[cc][dd] = hitp[aa][bb]) < 0) hitp[cc][dd]=1;
  322.  
  323.     if (tmp==LEMMING) {
  324.         if (rnd(100)<=9) {
  325.             mitem[aa][bb] = LEMMING;
  326.             know[aa][bb]=1;
  327.         }
  328.         else mitem[aa][bb] = 0;
  329.     }
  330.     else mitem[aa][bb] = 0;
  331.  
  332.     moved[cc][dd] = 1;
  333.  
  334.     if (tmp == LEPRECHAUN)/* leprechaun takes gold */
  335.         switch(i) {
  336.         case OGOLDPILE:  
  337.         case OMAXGOLD:  
  338.         case OKGOLD:
  339.         case ODGOLD:
  340.         case ODIAMOND:   
  341.         case ORUBY:     
  342.         case OEMERALD: 
  343.         case OSAPPHIRE:
  344.             item[cc][dd] = 0; 
  345.         };
  346.  
  347.     if (tmp == TROLL)  /* if a troll regenerate him */
  348.         if ((gtime & 1) == 0)
  349.             if (monster[tmp].hitpoints > hitp[cc][dd])  hitp[cc][dd]++;
  350.  
  351.     if (i==OTRAPARROW)    /* arrow hits monster */
  352.     { 
  353.         who = "An arrow";  
  354.         if ((hitp[cc][dd] -= rnd(10)+level) <= 0) { 
  355.             mitem[cc][dd]=0;  
  356.             flag=2; 
  357.         } 
  358.         else flag=1; 
  359.     }
  360.  
  361.     if (i==ODARTRAP)    /* dart hits monster */
  362.     { 
  363.         who = "A dart";  
  364.         if ((hitp[cc][dd] -= rnd(6)) <= 0) { 
  365.             mitem[cc][dd]=0;  
  366.             flag=2; 
  367.         } 
  368.         else flag=1; 
  369.     }
  370.  
  371.     if (tmp < DEMONLORD)
  372.         if (i==OTELEPORTER)    /* monster hits teleport trap */
  373.         { 
  374.             flag=3; 
  375.             fillmonst(mitem[cc][dd]);  
  376.             mitem[cc][dd]=0; 
  377.         }
  378.  
  379.     if (tmp < DEMONLORD)
  380.         if ((i==OELEVATORUP) || (i==OELEVATORDOWN)) {
  381.             mitem[cc][dd]=0;
  382.             flag=4;
  383.         }
  384.  
  385.     if (c[BLINDCOUNT]) return;    
  386.     /* if blind don't show where monsters are    */
  387.     if (know[cc][dd] & 1) {
  388.         p=0;
  389.         if (flag) cursors();
  390.         switch(flag) {
  391.         case 1: 
  392.             p="\n%s hits the %s";  
  393.             break;
  394.         case 2: 
  395.             p="\n%s hits and kills the %s";  
  396.             break;
  397.         case 3: 
  398.             p="\nThe %s%s gets teleported"; 
  399.             who="";  
  400.             break;
  401.         case 4: 
  402.             p="\nThe %s%s is carried away by an elevator!";
  403.             who="";
  404.             break;
  405.         };
  406.         if (p) { 
  407.             lprintf(p,who,monster[tmp].name); 
  408.             beep(); 
  409.         }
  410.     }
  411.  
  412.     if (know[aa][bb] & 1)   show1cell(aa,bb);
  413.     if (know[cc][dd] & 1)   show1cell(cc,dd);
  414. }
  415.  
  416. /*
  417.  *    movsphere()     Function to look for and move spheres of annihilation
  418.  *
  419.  *    This function works on the sphere linked list, first duplicating the list
  420.  *    (the act of moving changes the list), then processing each sphere in order
  421.  *    to move it.  They eat anything in their way, including stairs, volcanic
  422.  *    shafts, potions, etc, except for upper level demons, who can dispel
  423.  *    spheres.
  424.  *    No value is returned.
  425.  */
  426. #define SPHMAX 20    /* maximum number of spheres movsphere can handle */
  427. movsphere()
  428. {
  429.     register int x,y,dir,len;
  430.     register struct sphere *sp,*sp2;
  431.     struct sphere sph[SPHMAX];
  432.  
  433.     /* first duplicate sphere list */
  434.     /* look through sphere list */
  435.     for (sp=0,x=0,sp2=spheres; sp2; sp2=sp2->p)
  436.         /* only if this level */
  437.         if (sp2->lev == level) {
  438.             sph[x] = *sp2;    
  439.             sph[x++].p = 0;  /* copy the struct */
  440.             if (x>1)  
  441.                 sph[x-2].p = &sph[x-1]; /* link pointers */
  442.         }
  443.     if (x) sp= sph;    /* if any spheres, point to them */
  444.     else return;    /* no spheres */
  445.  
  446.     /* look through sphere list */
  447.     for (sp=sph; sp; sp=sp->p) {
  448.         x = sp->x;      
  449.         y = sp->y;
  450.         if (item[x][y]!=OANNIHILATION) continue;/* not really there */
  451.  
  452.         /* has sphere run out of gas? */
  453.         if (--(sp->lifetime) < 0) {
  454.             rmsphere(x,y); /* delete sphere */
  455.             continue;
  456.         }
  457.         /* time to move the sphere */
  458.         switch(rnd((int)max(7,c[INTELLIGENCE]>>1))) {
  459.         case 1:
  460.         case 2:        /* change direction to a random one */
  461.             sp->dir = rnd(8);
  462.         default:    /* move in normal direction */
  463.             dir = sp->dir;        
  464.             len = sp->lifetime;
  465.             rmsphere(x,y);
  466.             newsphere(x+diroffx[dir],y+diroffy[dir],dir,len);
  467.         };
  468.     }
  469. }
  470.